package me.gavincook.mybatis.plugins;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

/**
 * 批量插入
 *
 * @author gavincook
 * @version $ID: BatchInsertPlugin.java, v0.1 2018-01-08 11:48 gavincook Exp $$
 */
public class BatchInsertPlugin extends PluginAdapter {

    /** 默认忽略的字段，多个用逗号相隔 */
    private String defaultIgnoreColumnsConfig;

    /** 插件开关 */
    private boolean defaultPluginOn = true;

    @Override
    public boolean validate(List<String> warnings) {
        defaultIgnoreColumnsConfig = properties.getProperty("ignoreColumns");
        defaultPluginOn = Boolean.valueOf(properties.getProperty("pluginOn", "true"));
        return true;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass,
                                   IntrospectedTable introspectedTable) {
        boolean pluginOn = defaultPluginOn;
        //获取表格对插件的开关配置
        String pluginOnConfig = introspectedTable.getTableConfigurationProperty("pluginOn");
        if(pluginOnConfig != null){
            pluginOn = Boolean.valueOf(pluginOnConfig);
        }
        if(!pluginOn){
            return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
        }
        Method batchInsertMethod = new Method();

        //生成方法签名（部分）
        batchInsertMethod.setVisibility(JavaVisibility.PUBLIC);
        batchInsertMethod.setName("batchInsert");
        batchInsertMethod.setReturnType(FullyQualifiedJavaType.getIntInstance());

        //添加方法参数
        Parameter records = new Parameter(
            new FullyQualifiedJavaType("java.util.List<" + introspectedTable.getBaseRecordType() + ">"), "records");
        records.addAnnotation("@Param(\"records\")");
        batchInsertMethod.addParameter(records);

        //添加注释
        CommentGenerator commentGenerator = context.getCommentGenerator();
        commentGenerator.addGeneralMethodComment(batchInsertMethod, introspectedTable);
        interfaze.addMethod(batchInsertMethod);
        return super.clientGenerated(interfaze, topLevelClass, introspectedTable);
    }

    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        boolean pluginOn = defaultPluginOn;
        //获取表格对插件的开关配置
        String pluginOnConfig = introspectedTable.getTableConfigurationProperty("pluginOn");
        if(pluginOnConfig != null){
            pluginOn = Boolean.valueOf(pluginOnConfig);
        }
        if(!pluginOn){
            return super.sqlMapDocumentGenerated(document, introspectedTable);
        }

        //处理忽略的字段
        String ignoreColumnsConfig = defaultIgnoreColumnsConfig;
        String ignoreColumnsConfigForTable =  introspectedTable.getTableConfigurationProperty("ignoreColumns");
        if(ignoreColumnsConfigForTable != null){
            ignoreColumnsConfig = ignoreColumnsConfigForTable;
        }

        XmlElement rootElement = document.getRootElement();
        XmlElement insertElement = new XmlElement("insert");
        insertElement.addAttribute(new Attribute("id", "batchInsert"));
        Set<String> ignoreColumns = new HashSet<>();
        if (ignoreColumnsConfig != null && ignoreColumnsConfig.trim().length() != 0) {
            for (String ignoreColumn : ignoreColumnsConfig.split(",")) {
                ignoreColumns.add(ignoreColumn);
            }
        }
        StringBuilder insertSql = new StringBuilder();
        //注释
        insertSql.append("<!--\n" + "          WARNING - @mbg.generated\n"
                         + "          This element is automatically generated by MyBatis Generator, do not modify.\n"
                         + "          This element was generated on Thu Jan 18 18:22:30 CST 2018.\n" + "        -->");

        //插入sql
        insertSql.append("\n          insert into ").append(introspectedTable.getFullyQualifiedTableNameAtRuntime()).append(" (");
        boolean firstColumn = true;
        //遍历字段
        for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
            if (ignoreColumns.contains(column.getJavaProperty())
                || ignoreColumns.contains(column.getActualColumnName())) {
                continue;
            }
            if (!firstColumn) {
                insertSql.append(",");
            }
            insertSql.append(column.getActualColumnName());
            firstColumn = false;
        }
        insertSql.append(
            ") \n          values \n          <foreach item=\"record\" collection=\"records\"  open=\"(\" separator=\"),(\" close=\")\">")
            .append("\n          ");

        firstColumn = true;
        for (IntrospectedColumn column : introspectedTable.getAllColumns()) {
            if (ignoreColumns.contains(column.getJavaProperty())
                || ignoreColumns.contains(column.getActualColumnName())) {
                continue;
            }
            if (!firstColumn) {
                insertSql.append(",");
            }
            insertSql.append("#{record.").append(column.getJavaProperty()).append("}");
            firstColumn = false;
        }

        insertSql.append("\n          ").append("</foreach>");

        insertElement.addElement(new TextElement(insertSql.toString()));

        rootElement.addElement(insertElement);
        return super.sqlMapDocumentGenerated(document, introspectedTable);
    }

}
